package com.yindian.cos.monitor.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yindian.cos.monitor.model.Tracker;
import com.yindian.cos.monitor.properties.MonitorSpanProperties;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.ThreadContext;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

/**
 * tracker服务类，负责封装Tracker数据
 *
 * @author zhangchuanhao
 * @create 2018/11/6
 */
@Log4j2
public class TrackerService {

    public final static String TRACKER_ID = "trackerId";
    public final static String SPAN_ID = "spanId";
    public final static String TRACKER = "tracker";

    public static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 将请求放入当前线程
     */
    public static ThreadLocal<Tracker> trackerThreadLocal = new ThreadLocal();

    private final MonitorSpanProperties monitorSpanProperties;

    public TrackerService(MonitorSpanProperties monitorSpanProperties) {
        this.monitorSpanProperties = monitorSpanProperties;
    }

    /**
     * 获取trackerId
     *
     * @return
     */
    public static String getTrackerId() {
        return ThreadContext.get(TRACKER_ID);
    }

    /**
     * 设置trackerId
     *
     * @param trackerId
     */
    private static void setTrackerId(String trackerId) {
        ThreadContext.put(TRACKER_ID, trackerId);
    }

    /**
     * 设置当前spanId
     *
     * @param spanId
     */
    private static void setSpanId(String spanId) {
        ThreadContext.put(SPAN_ID, spanId);
    }

    /**
     * 获取当前tracker
     *
     * @return
     */
    public static Tracker getTracker() {
        return trackerThreadLocal.get();
    }

    /**
     * 设置tracker
     *
     * @param tracker
     */
    public static void setTracker(Tracker tracker) {
        trackerThreadLocal.set(tracker);
    }

    /**
     * 移除当前tracker
     */
    public static void removeTracker() {
        trackerThreadLocal.remove();
    }

    /**
     * 构建一个tracker放入trackerThreadLocal
     *
     * @param request
     */
    public void trackerStart(HttpServletRequest request) {
        // 从请求头里获取tracker_id，如果不存在就新建一个tracker_id放入当前线程
        String trackerId = request.getHeader(TRACKER_ID);
        if (StringUtils.isBlank(trackerId)) {
            trackerId = UUID.randomUUID().toString();
        }
        setTrackerId(trackerId);
        // 构造服务信息
        String spanId = UUID.randomUUID().toString();
        String node = monitorSpanProperties.getNode();
        String serverName = monitorSpanProperties.getServerName();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();

        // 封装请求的详细信息
        Tracker tracker = new Tracker(trackerId, spanId, node, serverName, url, uri, method);

        setSpanId(spanId);
        trackerThreadLocal.set(tracker);
        try {
            ThreadContext.put(TrackerService.TRACKER, TrackerService.objectMapper.writeValueAsString(tracker));
        } catch (JsonProcessingException e) {
            log.error("jackson转换json失败，{}", e);
        }
    }

    /**
     * 异步方法调用时重新写入Tracker信息
     *
     * @param tracker
     */
    public static void trackerStart(Tracker tracker) {
        setTrackerId(tracker.getTrackerId());
        setTracker(tracker);
        setSpanId(tracker.getSpanId());
    }

    /**
     * 执行成功后，清除数据
     */
    public static void trackerEnd() {
        ThreadContext.clearAll();
        removeTracker();
    }
}
